﻿using ST.Common.Util.Model;
using System;
using System.Collections.Generic;
using System.Text;

namespace ST.Common.Data
{
	public class IDGenerator
	{
		private static object lockObj = new object();
		private static int current = 1;

		#region 生成流水号
		/// <summary>
		/// 生成顺序的流水号（格式：前缀(2-4)+时间（(yy)yyMMddHHmmssfff）(15/17位)+sessionType(1位)+sessionID(6位)+顺序号(xxxxxx)(6+)）
		/// </summary>
		public static string[] Next(string prefixStr, int sessionType, int sessionID, int count, int maxBitLength, string format = "yyyyMMddHHmmssfff")
		{
			if (count <= 0)
			{
				throw new ArgumentException("数量不能小于1");
			}
			int maxValue = (int)Math.Pow(10, maxBitLength) - 1;//最大编号
			if (count > maxValue)
			{
				throw new ArgumentException("数量不能超过" + maxValue);
			}

			string[] result = new string[count];
			lock (lockObj)
			{
				DateTime dtNow = DateTime.Now;
				string timestamp = string.Empty;
				if (string.IsNullOrEmpty(format))
				{
					format = "yyyyMMddHHmmssfff";
				}
				timestamp = dtNow.ToString(format);

				string prefix = string.Empty;
				if (string.IsNullOrEmpty(prefixStr))
				{
					prefix = timestamp + sessionType + sessionID.ToString().PadLeft(6, '0');//todo：如果sessionID超过了范围怎么办
				}
				else
				{
					prefix = prefixStr + timestamp + sessionType + sessionID.ToString().PadLeft(6, '0');
				}
				if (current + count <= maxValue)
				{
					for (var i = 0; i < count; i++)
					{
						result[i] = prefix + (current + i).ToString().PadLeft(maxBitLength, '0');
					}
					current += count;
				}
				else
				{
					int total = 0;
					while (current <= maxValue)
					{
						result[total++] = prefix + (current++).ToString().PadLeft(maxBitLength, '0');
					}
					current = 1;
					while (total < count)
					{
						result[total++] = prefix + (current++).ToString().PadLeft(maxBitLength, '0');
					}
				}
			}
			return result;
		}

		/// <summary>
		/// 生成顺序的流水号（格式：前缀(2-4)+时间（(yy)yyMMddHHmmssfff）(15/17位)+sessionType(1位)+sessionID(6位)+顺序号(xxxxxx)(6+)）
		/// </summary>
		/// <param name="prefix"></param>
		/// <returns></returns>
		public static string[] Next(string prefixStr, int sessionType, int sessionID, int count)
		{
			return Next(prefixStr, sessionType, sessionID, count, 6, "yyyyMMddHHmmssfff");
		}

		/// <summary>
		/// 生成顺序的流水号（格式：前缀(2-4)+时间（(yy)yyMMddHHmmssfff）(15/17位)+sessionType(1位)+sessionID(6位)+顺序号(xxxxxx)(6+)）
		/// </summary>
		/// <param name="prefix"></param>
		/// <returns></returns>
		public static string[] Next(string prefixStr, UserSession sessionCurrent, int count)
		{
			return Next(prefixStr, sessionCurrent.SessionType, sessionCurrent.SessionID, count, 6, "yyyyMMddHHmmssfff");
		}

		/// <summary>
		/// 生成顺序的流水号（格式：前缀(2-4)+时间（(yy)yyMMddHHmmssfff）(15/17位)+sessionType(1位)+sessionID(6位)+顺序号(xxxxxx)(6+)）
		/// </summary>
		/// <param name="prefix"></param>
		/// <returns></returns>
		public static string Next(string prefixStr, int sessionType, int sessionID)
		{
			return Next(prefixStr, sessionType, sessionID, 1, 6, "yyyyMMddHHmmssfff")[0];
		}

		/// <summary>
		/// 生成顺序的流水号（格式：前缀(2-4)+时间（(yy)yyMMddHHmmssfff）(15/17位)+sessionType(1位)+sessionID(6位)+顺序号(xxxxxx)(6+)）
		/// </summary>
		/// <param name="prefix"></param>
		/// <returns></returns>
		public static string Next(string prefixStr, UserSession sessionCurrent)
		{
			return Next(prefixStr, sessionCurrent.SessionType, sessionCurrent.SessionID, 1, 6, "yyyyMMddHHmmssfff")[0];
		}

		public static string Next(string prefixStr, UserSession sessionCurrent, int maxBitLength, string format = "yyyyMMddHHmmssfff")
		{
			return Next(prefixStr, sessionCurrent.SessionType, sessionCurrent.SessionID, 1, maxBitLength, format)[0];
		}

		/// <summary>
		/// 生成顺序的流水号（格式：时间（yyyyMMddHHmmssfff）(17位)+sessionType(1位)+sessionID(6位)+顺序号(xxxxxx)(6+)）
		/// </summary>
		/// <returns></returns>
		public static string[] Next(int sessionType, int sessionID, int count)
		{
			return Next(null, sessionType, sessionID, count, 6, "yyyyMMddHHmmssfff");
		}

		/// <summary>
		/// 生成顺序的流水号（格式：时间（yyyyMMddHHmmssfff）(17位)+sessionType(1位)+sessionID(6位)+顺序号(xxxxxx)(6+)）
		/// </summary>
		/// <param name="count"></param>
		/// <returns></returns>
		public static string[] Next(UserSession sessionCurrent, int count)
		{
			return Next(null, sessionCurrent.SessionType, sessionCurrent.SessionID, count, 6, "yyyyMMddHHmmssfff");
		}

		/// <summary>
		/// 生成顺序的流水号（格式：时间（yyyyMMddHHmmssfff）(17位)+sessionType(1位)+sessionID(6位)+顺序号(xxxxxx)(6+)）
		/// </summary>
		/// <param name="count"></param>
		/// <returns></returns>
		public static string Next(int sessionType, int sessionID)
		{
			return Next(null, sessionType, sessionID, 1, 6, "yyyyMMddHHmmssfff")[0];
		}

		/// <summary>
		/// 生成顺序的流水号（格式：时间（yyyyMMddHHmmssfff）(17位)+sessionType(1位)+sessionID(6位)+顺序号(xxxxxx)(6+)）
		/// </summary>
		/// <param name="count"></param>
		/// <returns></returns>
		public static string Next(UserSession sessionCurrent)
		{
			return Next(null, sessionCurrent.SessionType, sessionCurrent.SessionID, 1, 6, "yyyyMMddHHmmssfff")[0];
		}

		/// <summary>
		/// 生成32位流水号（格式：时间（yyMMddHHmmss）(18位)+buzCode(2位十六进制形式)+userid或者appid(10位十六进制形式)+序号(4位)）
		/// </summary>
		/// <param name="dtNow"></param>
		/// <param name="userID"></param>
		/// <param name="buzCode"></param>
		/// <returns></returns>
		public static string NextSNo(DateTime dtNow, int userIDOrAppID, ushort buzCode, int index = 1)
		{
			return dtNow.Ticks.ToString().PadLeft(18, '0') + buzCode.ToString().PadLeft(2, '0') + userIDOrAppID.ToString("X2").PadLeft(8, '0') + index.ToString("X2").PadLeft(4, '0');
		}

		/// <summary>
		/// 生成流水号（格式：时间（yyMMddHHmmss）(12位)+buzCode(4位十六进制形式)+uid(8位十六进制形式)+id(8位十六进制形式)）
		/// </summary>
		/// <param name="id"></param>
		/// <returns></returns>
		public static string GenOutTradeNo(ushort buzCode, int uid, int id)
		{
			return DateTime.Now.ToString("yyMMddHHmmss") + buzCode.ToString("X2").PadLeft(4, '0') + uid.ToString("X2").PadLeft(8, '0') + id.ToString("X2").PadLeft(8, '0');
		}
		/// <summary>
		/// 生成流水号（格式：时间（yyMMddHHmmss）(12位)+buzCode(4位十六进制形式)+userid或者appid(8位十六进制形式)+id(8位十六进制形式)）
		/// </summary>
		/// <param name="id"></param>
		/// <returns></returns>
		public static string GenOutTradeNo(DateTime dtNow, ushort buzCode, int userIDOrAppID, int id)
		{
			return dtNow.ToString("yyMMddHHmmss") + buzCode.ToString("X2").PadLeft(4, '0') + userIDOrAppID.ToString("X2").PadLeft(8, '0') + id.ToString("X2").PadLeft(8, '0');
		}
		#endregion

		#region 生成随机ID
		/// <summary>
		/// 返回随机32位
		/// </summary>
		/// <param name="sessionType"></param>
		/// <param name="sessionID"></param>
		/// <returns></returns>
		public static string NextRand32(int sessionType, int sessionID)
		{
			return Next(null, sessionType, sessionID, 1, 8, "yyyyMMddHHmmssfff")[0];
		}

		/// <summary>
		/// 返回随机32位
		/// </summary>
		/// <param name="sessionType"></param>
		/// <param name="sessionID"></param>
		/// <returns></returns>
		public static string[] NextRand32(int sessionType, int sessionID, int count)
		{
			return Next(null, sessionType, sessionID, count, 8, "yyyyMMddHHmmssfff");
		}

		/// <summary>
		/// 返回随机32位
		/// </summary>
		/// <param name="sessionType"></param>
		/// <param name="sessionID"></param>
		/// <returns></returns>
		public static string NextRand32(UserSession sessionCurrent)
		{
			return Next(null, sessionCurrent.SessionType, sessionCurrent.SessionID, 1, 8, "yyyyMMddHHmmssfff")[0];
		}

		/// <summary>
		/// 返回随机32位
		/// </summary>
		/// <param name="sessionType"></param>
		/// <param name="sessionID"></param>
		/// <returns></returns>
		public static string[] NextRand32(UserSession sessionCurrent, int count)
		{
			return Next(null, sessionCurrent.SessionType, sessionCurrent.SessionID, count, 8, "yyyyMMddHHmmssfff");
		}
		#endregion
	}
}
